package org.bigk.invoices.actions.invoices;

import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Actions;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Namespaces;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.interceptor.validation.SkipValidation;
import org.bigk.invoices.Globals;
import org.bigk.invoices.actions.AbstractCRUDAction;
import org.bigk.invoices.exceptions.ServiceException;
import org.bigk.invoices.model.Invoice;
import org.bigk.invoices.model.InvoiceFilter;
import org.bigk.invoices.model.InvoicePosition;
import org.bigk.invoices.model.InvoicePurchaser;
import org.bigk.invoices.model.PaymentKind;
import org.bigk.invoices.services.InvoicesService;
import org.bigk.invoices.services.PaymentKindsService;
import org.bigk.invoices.utils.DisplayTagUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionContext;


@Controller("invoicesAction")
@Namespaces({@Namespace("/invoices"), @Namespace("/print/invoices")})
public class InvoicesAction extends AbstractCRUDAction<Invoice> {
	
	private static final Logger logger = LoggerFactory.getLogger(InvoicesAction.class);
	private static final long serialVersionUID = 3190832719110023997L;
	
	public static final String REDIRECT_CREATE_EDIT_REFRESH = "redirectCreateEditRefresh";
	public static final String REDIRECT_CREATE_INVOICE_POSITION = "createInvoicePosition";
	public static final String REDIRECT_CREATE_INVOICE_PURCHASER = "createInvoicePurchaser";
	public static final String REDIRECT_EDIT_INVOICE_POSITION = "editInvoicePosition";
	public static final String REDIRECT_EDIT_INVOICE_PURCHASER = "editInvoicePurchaser";
		
	@Autowired
	private InvoicesService invoicesService;
	
	@Autowired
	private PaymentKindsService paymentKindsService;
	
	private Long id;
	private Long pId;
	private InvoiceFilter filter;

	private List<PaymentKind> paymentKindsList;

	@Override
	public void prepare() throws Exception {
		logger.debug("prepare() - start");

		this.paymentKindsList = this.paymentKindsService.listAllItems();

		logger.debug("prepare() - end");
	}
	
	@Override
	public void prepareList() throws ServiceException {
		logger.debug("prepareList() - start");
		logger.debug("prepareList() - this.filter=[{}]");
		
		if (this.filter == null)
			this.filter = new InvoiceFilter();
		
		this.filter.setCurrentPage(DisplayTagUtils.getCurrentPage4Id("rs"));
		
		list = invoicesService.listItems4Page(this.filter);

		logger.debug("prepareList() - this.filter=[{}]");
		logger.debug("prepareList() - end");
	}

	@Action(value = "list",
			results = {
					@Result(name = LIST, location = "/pages/invoices/list.jsp")
			}
	)
	@Override
	public String list() throws ServiceException {
		return super.list();
	}
	
	@Override
	public void prepareCreate() throws ServiceException {
		this.model = this.invoicesService.prepareNewInvoice();
		InvoicesActionHelper.storeInvoiceInSession(this.model);
	}
	
	@Action(value = "create",
			results = {
					@Result(name = INPUT, location = "/pages/invoices/input.jsp")
			}
	)
	@Override
	public String create() throws ServiceException {
		return super.create();
	}

	@Override
	public void prepareSave() throws ServiceException {
		this.model = InvoicesActionHelper.retrieveInvoiceFromSession();
	}

	public void validateSave() {
		logger.debug("validateSave() - start");

		if (CollectionUtils.isEmpty(this.model.getInvoicePurchasers())) {
			addActionError(getText("errors.notempty.invoicePurchasers"));
		}

		if (CollectionUtils.isEmpty(this.model.getInvoicePositions())) {
			addActionError(getText("errors.notempty.invoicePositions"));
		}
		
		logger.debug("validateSave() - end");
	}
	
	@Action(value = "save",
			results = {
			@Result(name = INPUT, location = "/pages/invoices/input.jsp"),
					@Result(name = REDIRECT_LIST, type = "redirectAction", location = "list")
			}
	)
	@Override
	public String save() throws ServiceException {
		invoicesService.saveInvoice(model);
		addActionMessage(getText("msg.recordInsertedSuccess"));
		return REDIRECT_LIST;
	}

	@Override
	public void prepareEdit() throws ServiceException {
		this.model = invoicesService.getInvoice(id);
		InvoicesActionHelper.storeInvoiceInSession(this.model);
	}

	@Override
	public void prepareUpdate() throws ServiceException {
		logger.debug("prepareUpdate() - start");

		this.model = InvoicesActionHelper.retrieveInvoiceFromSession();

		logger.debug("prepareUpdate() - end");
	}

	@Action(value = "update",
			results = {
					@Result(name = INPUT, location = "/pages/invoices/input.jsp"),
					@Result(name = REDIRECT_LIST, type = "redirectAction", location = "list")
			}
	)
	@Override
	public String update() throws ServiceException {
		logger.debug("update() - start");

		invoicesService.updateInvoice(model);
		addActionMessage(getText("msg.recordUpdatedSuccess"));

		logger.debug("update() - end - return value=[{}]", REDIRECT_LIST);
		return REDIRECT_LIST;
	}

	public void prepareCreateEditRefresh() throws ServiceException {
		logger.debug("prepareCreateEditRefresh() - start");

		this.model = InvoicesActionHelper.retrieveInvoiceFromSession();

		logger.debug("prepareCreateEditRefresh() - end");
	}

	@Action(value = "createEditRefresh",
			results = {
					@Result(name = INPUT, location = "/pages/invoices/input.jsp")
			})
	@SkipValidation
	public String createEditRefresh() throws ServiceException {
		return INPUT;
	}

	@Override
	public void prepareShow() throws ServiceException {
		model = invoicesService.getInvoice(this.getId());
	}

	@Actions({
		@Action(value = "show",
				results = {@Result(location = "/pages/invoices/show.jsp"),
						   @Result(name = REDIRECT_LIST, type = "redirectAction", location = "list")}),
		@Action(value = "showDr",
				results = {@Result(location = "/pages/invoices/showDr.jsp")})
	})
	@Override
	public String show() throws ServiceException {
		return super.show();
	}
	
	@Override
	public void prepareDelete() throws ServiceException {
		model = invoicesService.getInvoice(id);
	}
	
	@Action(value = "delete",
			results = {
					@Result(name = REDIRECT_LIST, type = "redirectAction", location = "list")
			}
	)
	@Override
	public String delete() throws ServiceException {
		invoicesService.deleteInvoice(model);
		addActionMessage(getText("msg.recordDeletedSuccess"));
		return REDIRECT_LIST;
	}

	public void prepareCreateInvoicePosition() throws ServiceException {
		logger.debug("prepareCreateInvoicePosition() - start");
		
		this.model = InvoicesActionHelper.retrieveInvoiceFromSession();
		
		logger.debug("prepareCreateInvoicePosition() - end");
	}

	@Action(value = "createInvoicePosition",
			results = {
				@Result(name = REDIRECT_CREATE_INVOICE_POSITION,
						type = "redirectAction",
						params = {"namespace", "/invoicesPositions", "actionName", "create"})
			})
	@SkipValidation
	public String createInvoicePosition() throws ServiceException {
		logger.debug("createInvoicePosition() - start");

		InvoicesActionHelper.storeInvoiceInSession(this.model);
		
		logger.debug("createInvoicePosition() - end - return value=[{}]", REDIRECT_CREATE_INVOICE_POSITION);
		return REDIRECT_CREATE_INVOICE_POSITION;
	}

	public void prepareEditInvoicePosition() throws ServiceException {
		logger.debug("prepareEditInvoicePosition() - start");

		this.model = InvoicesActionHelper.retrieveInvoiceFromSession();
		
		logger.debug("prepareEditInvoicePosition() - end");
	}

	@Action(value = "editInvoicePosition",
			results = {
				@Result(name = REDIRECT_EDIT_INVOICE_POSITION,
						type = "redirectAction",
						params = {"namespace", "/invoicesPositions",
									"actionName", "edit", "pId", "${pId}"
						})
			})
	@SkipValidation
	public String editInvoicePosition() throws ServiceException {
		logger.debug("editInvoicePosition() - start");

		InvoicesActionHelper.storeInvoiceInSession(this.model);
		
		logger.debug("editInvoicePosition() - end - return value=[{}]", REDIRECT_EDIT_INVOICE_POSITION);
		return REDIRECT_EDIT_INVOICE_POSITION;
	}
	
	public void prepareCreateInvoicePurchaser() throws ServiceException {
		logger.debug("prepareCreateInvoicePurchaser() - start");
		this.model = InvoicesActionHelper.retrieveInvoiceFromSession();
		logger.debug("prepareCreateInvoicePurchaser() - end");
	}

	@Action(value = "createInvoicePurchaser",
			results = {
				@Result(name = REDIRECT_CREATE_INVOICE_PURCHASER,
						type = "redirectAction",
						params = {"namespace", "/invoicesPurchasers", "actionName", "create"})
			})
	@SkipValidation
	public String createInvoicePurchaser() throws ServiceException {
		logger.debug("createInvoicePurchaser() - start");
		
		InvoicesActionHelper.storeInvoiceInSession(this.model);
		
		logger.debug("createInvoicePurchaser() - end - return value=[{}]", REDIRECT_CREATE_INVOICE_PURCHASER);
		return REDIRECT_CREATE_INVOICE_PURCHASER;
	}
	
	public void prepareEditInvoicePurchaser() throws ServiceException {
		logger.debug("prepareEditInvoicePurchaser() - start");

		this.model = InvoicesActionHelper.retrieveInvoiceFromSession();
		
		logger.debug("prepareEditInvoicePurchaser() - end");
	}

	@Action(value = "editInvoicePurchaser",
			results = {
				@Result(name = REDIRECT_EDIT_INVOICE_PURCHASER,
						type = "redirectAction",
						params = {"namespace", "/invoicesPurchasers",
									"actionName", "edit", "pId", "${pId}"
						})
			})
	@SkipValidation
	public String editInvoicePurchaser() throws ServiceException {
		logger.debug("editInvoicePurchaser() - start");

		InvoicesActionHelper.storeInvoiceInSession(this.model);
		
		logger.debug("editInvoicePurchaser() - end - return value=[{}]", REDIRECT_EDIT_INVOICE_PURCHASER);
		return REDIRECT_EDIT_INVOICE_PURCHASER;
	}
	
	public void prepareDeleteInvoicePosition() throws ServiceException {
		logger.debug("prepareDeleteInvoicePosition() - start");

		Map<String, Object> session = ActionContext.getContext().getSession();
		this.model = (Invoice) session.get(Globals.SP_INVOICE);
		
		logger.debug("prepareDeleteInvoicePosition() - end");
	}

	@Action(value = "deleteInvoicePosition",
			results = {
				@Result(name = REDIRECT_CREATE_EDIT_REFRESH,
						type = "redirectAction",
						params = {"actionName", "createEditRefresh"})
			})
	@SkipValidation
	public String deleteInvoicePosition() throws ServiceException {
		logger.debug("deleteInvoicePosition() - start");

		int pid = this.getPId().intValue();

		logger.debug("deleteInvoicePosition() - pid=[{}]", pid);

		List<InvoicePosition> sInvoicePositions = this.model.getInvoicePositions();
		logger.debug("before removal - sInvoicePositions=[{}]", CollectionUtils.size(sInvoicePositions));

		sInvoicePositions.remove(pid);
		logger.debug("after removal - sInvoicePositions=[{}]", CollectionUtils.size(sInvoicePositions));
		
		logger.debug("deleteInvoicePosition() - end - return value=[{}]", REDIRECT_CREATE_EDIT_REFRESH);
		return REDIRECT_CREATE_EDIT_REFRESH;
	}
	
	public void prepareDeleteInvoicePurchaser() throws ServiceException {
		logger.debug("prepareDeleteInvoicePurchaser() - start");

		Map<String, Object> session = ActionContext.getContext().getSession();
		this.model = (Invoice) session.get(Globals.SP_INVOICE);
		
		logger.debug("prepareDeleteInvoicePurchaser() - end");
	}

	
	@Action(value = "deleteInvoicePurchaser",
			results = {
				@Result(name = REDIRECT_CREATE_EDIT_REFRESH,
						type = "redirectAction",
						params = {"actionName", "createEditRefresh"})
			})
	@SkipValidation
	public String deleteInvoicePurchaser() throws ServiceException {
		logger.debug("deleteInvoicePurchaser() - start");

		int pid = this.getPId().intValue();
		logger.debug("deleteInvoicePurchaser() - pid=[{}]", pid);

		List<InvoicePurchaser> sInvoicePurchasers = this.model.getInvoicePurchasers();
		logger.debug("before removal - sInvoicePurchasers=[{}]", CollectionUtils.size(sInvoicePurchasers));

		sInvoicePurchasers.remove(pid);
		logger.debug("after removal - sInvoicePurchasers=[{}]", CollectionUtils.size(sInvoicePurchasers));
		
		logger.debug("deleteInvoicePurchaser() - end - return value=[{}]", REDIRECT_CREATE_EDIT_REFRESH);
		return REDIRECT_CREATE_EDIT_REFRESH;
	}
	
	public void prepareBackToList() throws ServiceException {
		logger.debug("prepareBackToList() - start");

		this.model = new Invoice();

		logger.debug("prepareBackToList() - end");
	}
	
	@Action(value = "backToList",
			results = {
				@Result(name = REDIRECT_LIST, type = "redirectAction", location = "list")
			}
	)
	@SkipValidation
	public String backToList() throws ServiceException {
		logger.debug("backToList() - start - end - return value=[{}]", REDIRECT_LIST);
		return REDIRECT_LIST;
	}

	public InvoiceFilter getFilter() {
		return filter;
	}

	public void setFilter(InvoiceFilter filter) {
		this.filter = filter;
	}
	
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Long getPId() {
		return pId;
	}

	public void setPId(Long id) {
		pId = id;
	}

	public List<PaymentKind> getPaymentKindsList() {
		return paymentKindsList;
	}

	public void setPaymentKindsList(List<PaymentKind> paymentKindsList) {
		this.paymentKindsList = paymentKindsList;
	}
}
